package com.terrynoya.fight.scriptEngine
{
	import com.terrynoya.fight.evaluation.Char;

	public class TokenParser
	{
		private var _position:int;
		
		public static const INIT:int = 0;
		public static const NUM:int = 1;
		public static const ID:int = 2;
		public static const SYMBLE:int = 3;
		public static const DONE:int = 4;
		
		private var _text:String;
		
		private var _state:int;
		
		private var _tokens:Array;
		
		public function TokenParser()
		{
			
		}
		
		public function parse(value:String):Array
		{
			this._tokens = new Array(); 
			this._text = value;
			this._position = 0;
			this._state = INIT;
			while(this._position < value.length)
			{
				switch(this._state)
				{
					case INIT:
					{
						this.initState();
						break;
					}
					case NUM:
					{
						this.numState();						
						break;
					}
					case SYMBLE:
					{
						this.symbolState();
						break;
					}
					case ID:
					{
						this.idState();
						break;
					}
				}
			}
			return this._tokens;
		}
		
		/**
		 * 解析id = letter (letter|digit)* 
		 * 
		 */		
		private function idState():void
		{
			var val:String = this.read();
			var state:Boolean = true;
			while(state)
			{
				if(Char.isLetterOrDigit(this.getChar()))
				{
					val += this.read();
				}
				else
				{
					var vo:TokenVO = new TokenVO(this.getSymbolType(val),val);
					this._tokens.push(vo);
					this._state = INIT;			
					return;
				}
			}
		}
		
		/**
		 * 运算符 + - * / 
		 * 
		 */		
		private function symbolState():void
		{
			var val:String = this.read();
			if((val == "&" || val == "|") && this.getChar() == val)
			{
				val += this.read();
			}
			else if((val == ">" || val == "<" || val == "=" || val == "!") && this.getChar() == "=")
			{
				val += this.read();
			}
			var vo:TokenVO = new TokenVO(this.getSymbolType(val),val);
			this._tokens.push(vo);
			this._state = INIT;
		}
		
		private function getSymbolType(value:String):int
		{
			var rlt:int = TokenVO.ID;
			if(value == KeyWord.IF)
			{
				rlt = TokenVO.IF;
			}
			else if(value == KeyWord.LEFT_BRACKET)
			{
				rlt = TokenVO.LEFT_BRACKET;
			}
			else if(value == KeyWord.RIGHT_BRACKET)
			{
				rlt = TokenVO.RIGHT_BRACKET;
			}
			else if(value == KeyWord.ELSE)
			{
				rlt = TokenVO.ELSE;	
			}
			else if(value == KeyWord.ADD || value == KeyWord.MINUS)
			{
				rlt = TokenVO.ADD_OPER;
			}
			else if(value == KeyWord.MULTIPLY || value == KeyWord.DIVIDE)
			{
				rlt = TokenVO.MUTI_OPER;
			}
			else if(value == KeyWord.LARGER_THAN || value == KeyWord.LESS_THAN || value == KeyWord.EQUAL)
			{
				rlt = TokenVO.COMPAR_OP;
			}
			else if(value == KeyWord.LOGIC_AND || value == KeyWord.LOGIC_OR)
			{
				rlt = TokenVO.LOGIC_OP;
			}
			return rlt;
		}
		
		/**
		 * number = digit digit*; 
		 * 
		 */		
		private function numState():void
		{
			var numberVal:String = this.read();
			var state:Boolean = true;
			while(state)
			{
				if(Char.isDigit(this.getChar()))
				{
					numberVal += this.read();
				}
				else 
				{
					var vo:TokenVO = new TokenVO(TokenVO.NUMBER,numberVal);
					this._tokens.push(vo);
					this._state = INIT;
					return;
				}
			}
		}
		
		private function initState():void
		{
			if(this.getChar() == " ")
			{
				this.read();
				this._state = INIT;
			}
			else if(Char.isDigit(this.getChar()))
			{
				this._state = NUM;
			}
			else if(Char.isLetter(this.getChar()))
			{
				this._state = ID;
			}
			else if(!Char.isLetterOrDigit(this.getChar()))
			{
				this._state = SYMBLE;
			}
		}
		
		public function read():String 
		{
			var str:String = this._text.charAt(this._position);
			this._position ++;
			return str;
		}
		
		public function getChar():String 
		{
			return this._text.charAt(this._position);
		}
		
		private function match(value:String):Boolean
		{
			return value == value.charAt(this._position);
		}
	}
}